# 系统健康检查命令
from django.core.management.base import BaseCommand
from django.db import connection
from django.contrib.auth.models import User
from django.utils import timezone
from datetime import timedelta
import os
import psutil

from assets.models import Asset, AssetCategory, Department, Organization
from assets.models_system import SystemLog, SystemParameter, DataBackup
from assets.models_transfer import AssetTransfer
from assets.models_ai import AssetRecommendation, AssetAnomalyDetection


class Command(BaseCommand):
    help = '执行系统健康检查'

    def add_arguments(self, parser):
        parser.add_argument(
            '--detailed',
            action='store_true',
            help='显示详细检查信息'
        )

    def handle(self, *args, **options):
        detailed = options['detailed']
        
        self.stdout.write('=' * 60)
        self.stdout.write(self.style.SUCCESS('固定资产管理系统健康检查'))
        self.stdout.write('=' * 60)
        
        # 数据库连接检查
        self.check_database_connection()
        
        # 数据统计
        self.check_data_statistics()
        
        # 系统资源检查
        self.check_system_resources()
        
        # 配置检查
        self.check_system_configuration()
        
        # 日志检查
        self.check_system_logs()
        
        # 备份检查
        self.check_backup_status()
        
        # AI功能检查
        self.check_ai_features()
        
        if detailed:
            self.detailed_checks()
        
        self.stdout.write('=' * 60)
        self.stdout.write(self.style.SUCCESS('健康检查完成'))
        self.stdout.write('=' * 60)

    def check_database_connection(self):
        """检查数据库连接"""
        self.stdout.write('\n📊 数据库连接检查')
        self.stdout.write('-' * 30)
        
        try:
            with connection.cursor() as cursor:
                cursor.execute("SELECT 1")
                result = cursor.fetchone()
                if result:
                    self.stdout.write(self.style.SUCCESS('✓ 数据库连接正常'))
                else:
                    self.stdout.write(self.style.ERROR('✗ 数据库连接异常'))
        except Exception as e:
            self.stdout.write(self.style.ERROR(f'✗ 数据库连接失败: {e}'))

    def check_data_statistics(self):
        """检查数据统计"""
        self.stdout.write('\n📈 数据统计')
        self.stdout.write('-' * 30)
        
        try:
            # 基础数据统计
            user_count = User.objects.count()
            org_count = Organization.objects.count()
            dept_count = Department.objects.count()
            category_count = AssetCategory.objects.count()
            asset_count = Asset.objects.count()
            
            self.stdout.write(f'用户数量: {user_count}')
            self.stdout.write(f'组织数量: {org_count}')
            self.stdout.write(f'部门数量: {dept_count}')
            self.stdout.write(f'资产类别: {category_count}')
            self.stdout.write(f'资产总数: {asset_count}')
            
            # 业务数据统计
            transfer_count = AssetTransfer.objects.count()
            recommendation_count = AssetRecommendation.objects.count()
            anomaly_count = AssetAnomalyDetection.objects.count()
            
            self.stdout.write(f'调拨记录: {transfer_count}')
            self.stdout.write(f'智能推荐: {recommendation_count}')
            self.stdout.write(f'异常检测: {anomaly_count}')
            
            # 数据完整性检查
            if asset_count > 0:
                assets_without_category = Asset.objects.filter(category__isnull=True).count()
                if assets_without_category > 0:
                    self.stdout.write(
                        self.style.WARNING(f'⚠ 发现 {assets_without_category} 个资产未分配类别')
                    )
                else:
                    self.stdout.write(self.style.SUCCESS('✓ 所有资产都已分配类别'))
            
        except Exception as e:
            self.stdout.write(self.style.ERROR(f'✗ 数据统计检查失败: {e}'))

    def check_system_resources(self):
        """检查系统资源"""
        self.stdout.write('\n💻 系统资源检查')
        self.stdout.write('-' * 30)
        
        try:
            # CPU使用率
            cpu_percent = psutil.cpu_percent(interval=1)
            if cpu_percent < 80:
                self.stdout.write(self.style.SUCCESS(f'✓ CPU使用率: {cpu_percent}%'))
            else:
                self.stdout.write(self.style.WARNING(f'⚠ CPU使用率较高: {cpu_percent}%'))
            
            # 内存使用率
            memory = psutil.virtual_memory()
            memory_percent = memory.percent
            if memory_percent < 80:
                self.stdout.write(self.style.SUCCESS(f'✓ 内存使用率: {memory_percent}%'))
            else:
                self.stdout.write(self.style.WARNING(f'⚠ 内存使用率较高: {memory_percent}%'))
            
            # 磁盘使用率
            disk = psutil.disk_usage('/')
            disk_percent = (disk.used / disk.total) * 100
            if disk_percent < 80:
                self.stdout.write(self.style.SUCCESS(f'✓ 磁盘使用率: {disk_percent:.1f}%'))
            else:
                self.stdout.write(self.style.WARNING(f'⚠ 磁盘使用率较高: {disk_percent:.1f}%'))
                
        except Exception as e:
            self.stdout.write(self.style.ERROR(f'✗ 系统资源检查失败: {e}'))

    def check_system_configuration(self):
        """检查系统配置"""
        self.stdout.write('\n⚙️ 系统配置检查')
        self.stdout.write('-' * 30)
        
        try:
            # 检查关键配置参数
            key_params = [
                'system.name',
                'asset.auto_generate_number',
                'inventory.low_stock_threshold',
                'ai.recommendation_enabled',
            ]
            
            for param_key in key_params:
                try:
                    param = SystemParameter.objects.get(key=param_key)
                    self.stdout.write(f'✓ {param.name}: {param.value}')
                except SystemParameter.DoesNotExist:
                    self.stdout.write(
                        self.style.WARNING(f'⚠ 缺少配置参数: {param_key}')
                    )
            
            # 检查媒体文件目录
            from django.conf import settings
            media_root = getattr(settings, 'MEDIA_ROOT', None)
            if media_root and os.path.exists(media_root):
                self.stdout.write(self.style.SUCCESS(f'✓ 媒体文件目录存在: {media_root}'))
            else:
                self.stdout.write(self.style.WARNING('⚠ 媒体文件目录不存在'))
                
        except Exception as e:
            self.stdout.write(self.style.ERROR(f'✗ 系统配置检查失败: {e}'))

    def check_system_logs(self):
        """检查系统日志"""
        self.stdout.write('\n📝 系统日志检查')
        self.stdout.write('-' * 30)
        
        try:
            # 检查最近的日志
            recent_logs = SystemLog.objects.filter(
                created_at__gte=timezone.now() - timedelta(days=1)
            )
            
            total_logs = recent_logs.count()
            error_logs = recent_logs.filter(level='ERROR').count()
            warning_logs = recent_logs.filter(level='WARNING').count()
            
            self.stdout.write(f'最近24小时日志总数: {total_logs}')
            
            if error_logs > 0:
                self.stdout.write(
                    self.style.ERROR(f'✗ 发现 {error_logs} 条错误日志')
                )
            else:
                self.stdout.write(self.style.SUCCESS('✓ 无错误日志'))
            
            if warning_logs > 0:
                self.stdout.write(
                    self.style.WARNING(f'⚠ 发现 {warning_logs} 条警告日志')
                )
            else:
                self.stdout.write(self.style.SUCCESS('✓ 无警告日志'))
                
        except Exception as e:
            self.stdout.write(self.style.ERROR(f'✗ 系统日志检查失败: {e}'))

    def check_backup_status(self):
        """检查备份状态"""
        self.stdout.write('\n💾 备份状态检查')
        self.stdout.write('-' * 30)
        
        try:
            # 检查最近的备份
            recent_backups = DataBackup.objects.filter(
                created_at__gte=timezone.now() - timedelta(days=7)
            )
            
            total_backups = recent_backups.count()
            completed_backups = recent_backups.filter(status='completed').count()
            failed_backups = recent_backups.filter(status='failed').count()
            
            self.stdout.write(f'最近7天备份总数: {total_backups}')
            self.stdout.write(f'成功备份: {completed_backups}')
            
            if failed_backups > 0:
                self.stdout.write(
                    self.style.ERROR(f'✗ 失败备份: {failed_backups}')
                )
            else:
                self.stdout.write(self.style.SUCCESS('✓ 无失败备份'))
            
            # 检查最新备份时间
            latest_backup = DataBackup.objects.filter(
                status='completed'
            ).order_by('-completed_at').first()
            
            if latest_backup:
                days_since_backup = (timezone.now() - latest_backup.completed_at).days
                if days_since_backup <= 1:
                    self.stdout.write(
                        self.style.SUCCESS(f'✓ 最新备份: {latest_backup.completed_at.strftime("%Y-%m-%d %H:%M")}')
                    )
                else:
                    self.stdout.write(
                        self.style.WARNING(f'⚠ 最新备份时间: {latest_backup.completed_at.strftime("%Y-%m-%d %H:%M")} ({days_since_backup}天前)')
                    )
            else:
                self.stdout.write(self.style.WARNING('⚠ 未找到成功的备份记录'))
                
        except Exception as e:
            self.stdout.write(self.style.ERROR(f'✗ 备份状态检查失败: {e}'))

    def check_ai_features(self):
        """检查AI功能"""
        self.stdout.write('\n🤖 AI功能检查')
        self.stdout.write('-' * 30)
        
        try:
            # 检查AI功能是否启用
            ai_enabled = SystemParameter.get_param('ai.recommendation_enabled', False)
            anomaly_enabled = SystemParameter.get_param('ai.anomaly_detection_enabled', False)
            
            if ai_enabled:
                self.stdout.write(self.style.SUCCESS('✓ 智能推荐功能已启用'))
            else:
                self.stdout.write(self.style.WARNING('⚠ 智能推荐功能未启用'))
            
            if anomaly_enabled:
                self.stdout.write(self.style.SUCCESS('✓ 异常检测功能已启用'))
            else:
                self.stdout.write(self.style.WARNING('⚠ 异常检测功能未启用'))
            
            # 检查AI数据
            recent_recommendations = AssetRecommendation.objects.filter(
                created_at__gte=timezone.now() - timedelta(days=7)
            ).count()
            
            recent_anomalies = AssetAnomalyDetection.objects.filter(
                detected_at__gte=timezone.now() - timedelta(days=7)
            ).count()
            
            self.stdout.write(f'最近7天推荐数: {recent_recommendations}')
            self.stdout.write(f'最近7天异常检测: {recent_anomalies}')
            
        except Exception as e:
            self.stdout.write(self.style.ERROR(f'✗ AI功能检查失败: {e}'))

    def detailed_checks(self):
        """详细检查"""
        self.stdout.write('\n🔍 详细检查')
        self.stdout.write('-' * 30)
        
        try:
            # 检查孤立数据
            orphaned_assets = Asset.objects.filter(
                department__isnull=True,
                user__isnull=True
            ).count()
            
            if orphaned_assets > 0:
                self.stdout.write(
                    self.style.WARNING(f'⚠ 发现 {orphaned_assets} 个未分配的资产')
                )
            
            # 检查过期数据
            expired_recommendations = AssetRecommendation.objects.filter(
                expires_at__lt=timezone.now(),
                is_dismissed=False,
                is_accepted=False
            ).count()
            
            if expired_recommendations > 0:
                self.stdout.write(
                    self.style.WARNING(f'⚠ 发现 {expired_recommendations} 个过期的推荐')
                )
            
            # 检查长时间未处理的异常
            old_anomalies = AssetAnomalyDetection.objects.filter(
                detected_at__lt=timezone.now() - timedelta(days=30),
                is_resolved=False
            ).count()
            
            if old_anomalies > 0:
                self.stdout.write(
                    self.style.WARNING(f'⚠ 发现 {old_anomalies} 个长时间未处理的异常')
                )
            
        except Exception as e:
            self.stdout.write(self.style.ERROR(f'✗ 详细检查失败: {e}'))